import re

from myelin.Ns import MYELINS, XML_NS
from myelin.lib import DateTime

from nodetypes.ntypes import Action

class Account(object):
    __slots__ = ()
    
    newDateTimeString = staticmethod(DateTime.ToString)
    isTimeZoneString = staticmethod(DateTime.IsTzStr)
    addNewResouceServiceType = Action.AddNewResourceService
    
    def createAccount(self, context, node):
        session = context.session
        
        node.xml_set_attribute(
            (u'remote-ip',None),
            unicode(session.remote_ip)
        )
        
        if session.isPersistent():
            node.xml_set_attribute(
                (u'session-id',None),
                unicode(session.id)
            )
            
        return node
    
    def setTimezone(self, context, timezone):
        if timezone and self.isTimeZoneString(timezone):
            if __debug__:
                print "Current timezone set to: %s" % (timezone)
            return timezone[0]
        if __debug__:
            print "Current timezone set to: %s" % (context.defaults.default_timezone)
        return context.defaults.default_timezone
    
    def setLocale(self, context, locale):
        preferences = context.preferences
        if locale not in context.i18nResources and \
            'locale' in preferences:
            return preferences['locale']
            
        localeS = locale.split('-')
        lang = localeS[0]
        region = len(localeS) == 2 and localeS[1] or ''
        
        preferences['locale'] = locale
        preferences['lang'] = lang
        preferences['region'] = region
        
        if __debug__:
            print "Current locale set to: %s" % (locale)
        
        return locale
    
    def setTheme(self, context, theme):
        preferences = context.preferences
        print "i18nResources: %s" % context.i18nResources
        i18nMapper = context.i18nResources.get(preferences.get('locale'))
        print "i18nMapper: %s" % str(i18nMapper.themes)
        if i18nMapper and theme in i18nMapper.themes:
            preferences['theme'] = theme
            return theme
        if preferences.has_key('theme'):
            return preferences['theme']
        theme = i18nMapper.default_theme or context.defaults.default_theme
        preferences['theme'] = theme
        
        if __debug__:
            print "Current theme set to: %s" % (theme)
        
        return theme
    
    def createAdminNodeAcls(self, context, node):    
        
        node = node.xml_append(
            node.xml_create_element(
                u'a:node-acls', MYELINS
            )
        )
        
        newact = node.xml_append(
            node.xml_create_element(
                u'a:acl-group', MYELINS,
                attributes = {
                    u'name' : u'new-node-types',
                }
            )
        )
        action = context.action
        for k,a in context.nodeType.actions.items():
            if k == action:
                attr = {
                    u'key' : unicode(k),
                    u'selected' : u'1',
                }
            else:
                attr = {
                    u'key' : unicode(k),
                }
            if isinstance(a, self.addNewResouceServiceType):
                newact.xml_append(
                    newact.xml_create_element(
                        u'a:acl', MYELINS,
                        attributes = attr,
                    )
                )
            else:
                node.xml_append(
                    node.xml_create_element(
                        u'a:acl', MYELINS,
                        attributes = attr,
                    )
                )
                
        return node
    
    def createUserNodeAcls(self, context, node):
        node = node.xml_append(
            node.xml_create_element(
                u'a:node-acls', MYELINS
            )
        )
        
        newact = node.xml_append(
            node.xml_create_element(
                u'a:acl-group', MYELINS,
                attributes = {
                    u'name' : u'new-node-types',
                }
            )
        )
        
        acls = context.acls.base
        action = context.action
        
        actions = context.nodeType.actions
        
        k = actions.keys()
        k.sort()        
        
        for k in k:
            if k in acls:
                if k == action:
                    a = {
                        u'key' : unicode(k),
                        u'selected' : u'1',
                    }
                else:
                    a = {
                        u'key' : unicode(k),
                    }
                    
                if isinstance(actions[k], self.addNewResouceServiceType):
                    n = newact.xml_append(
                        newact.xml_create_element(
                            u'a:acl', MYELINS,
                            attributes = a
                        )
                    )
                else:
                    n = node.xml_append(
                        node.xml_create_element(
                            u'a:acl', MYELINS,
                            attributes = a
                        )
                    )
        return node
    
    
    def findDomainProfile(self, profile):
        for locale in profile.dcLanguage:
            for p in profile.mParent:
                if locale in p.dcLanguage:
                    return p
            for t in profile.mTranslation_Of:
                for p in t.mParent:
                    if locale in p.dcLanguage:
                        return p         

class GuestAccount(Account):
    __slots__ = ()
    
    def createAccount(self, context, node, locale):    
        super(GuestAccount, self).createAccount(context, node)
        
        self.createUserNodeAcls(context, node)
        
        # preferences
        prefsNode = node.xml_create_element(u'a:preferences', MYELINS)
        node.xml_append(prefsNode)
        
        defaults = context.defaults
        args = context.request.args
        
        a_has = args.has_key
        a_pop = args.pop
        
        locale = self.setLocale(context, a_has('locale') and unicode(a_pop('locale')[0]))
        theme = self.setTheme(context, a_has('theme') and unicode(a_pop('theme')[0]))
        timezone = defaults.default_timezone
            
        prefsNode.xml_set_attribute((u'locale',None), locale)
        prefsNode.xml_set_attribute((u'theme',None), theme)
        prefsNode.xml_set_attribute((u'timezone',None), timezone)
        
        # profile ids
        node.xml_append(
            node.xml_create_element(
                u'a:profile', MYELINS
            )
        )
        
        # update cacheable
        cacheable = context.cacheable
        if cacheable:
            #cacheable.updateParam('action', context.action)
            #cacheable.updateParam('method', context.method)
            cacheable.updateParam('locale',locale)
            cacheable.updateParam('theme',theme)
            cacheable.updateParam('tz',timezone)
            
        # set root xml:lang to preferences locale
        node.rootNode.childNodes[0].xml_set_attribute(
            (u'xml:lang',XML_NS),
            locale
        )
        
        #context.docIdParams.update(
        #    (
        #        theme,
        #        timezone,
        #        locale
        #    ),
        #)
        
        return node


class AgentAccount(Account):
    __slots__ = ()
    
    
    def createAccount(self, context, node, locale):
        super(AgentAccount, self).createAccount(context, node)
        
        map = context.uriMapper.apply
        
        # extract
        account = context.account
            
        # account base
        node.xml_set_attribute((u'node-id',None), unicode(account.accountId))
        node.xml_set_attribute((u'logged-in',None), u'1')
        node.xml_set_attribute((u'user-id',None), unicode(account.agentId))
        node.xml_set_attribute((u'domain-id',None), unicode(account.domainId))
        
        # is admin
        if account.isAdmin:
            node.xml_set_attribute((u'is-admin',None),u'1')
            self.createAdminNodeAcls(context, node)
        else:
            self.createUserNodeAcls(context, node)
            
        # preferences
        prefsNode = node.xml_create_element(u'a:preferences', MYELINS)
        node.xml_append(prefsNode)
        
        defaults = context.defaults
        args = context.request.args
        
        a_has = args.has_key
        a_pop = args.pop
        
        prefs = account.getPreferences(defaults)
        if prefs:
            #prefsNode.xml_set_attribute((u'node-id',None), map(prefs.rdf_value))
            locale = self.setLocale(context, prefs.mLocale and unicode(prefs.mLocale[0]) or a_has('locale') and unicode(a_pop('locale')[0]))
            theme = self.setTheme(context, prefs.mTheme and unicode(prefs.mTheme[0]) or a_has('theme') and unicode(a_pop('theme')[0]))
            timezone = self.setTimezone(context, prefs.mTimezone)
        else:
            locale = self.setLocale(context, a_has('locale') and unicode(a_pop('locale')[0]))
            theme = self.setTheme(context, a_has('theme') and unicode(a_pop('theme')[0]))
            timezone = defaults.default_timezone
            
        prefsNode.xml_set_attribute((u'locale',None), locale)
        prefsNode.xml_set_attribute((u'theme',None), theme)
        prefsNode.xml_set_attribute((u'timezone',None), timezone)
                
        profile = account.getProfile(context, locale)
        if profile:
            node.xml_append(
                node.xml_create_element(
                    u'a:profile', MYELINS,
                    attributes={
                        u'agent-id' : account.agentId,
                        u'nick' : account.agentQName[0],
                        u'node-id' : profile.rdf_value,
                        u'uri': map(profile.rdf_getDomain()),
                    }
                )
            )
            #profile = self.findDomainProfile(profile)
            #if profile:
            #    profileNode.xml_set_attribute((u'domain-id',None), profile.rdf_value)
        else:
            node.xml_append(
                node.xml_create_element(
                    u'a:profile', MYELINS,
                    attributes={
                        u'agent-id' : account.agentId,
                        u'nick' : account.agentQName[0]
                    }
                )
            )
                
        # update cacheable
        #cacheable = context.cacheable
        #if cacheable:
        #    cacheable.updateParam('action', context.action)
        #    cacheable.updateParam('method', context.method)
            #cacheable.updateParam('locale',locale)
            #cacheable.updateParam('theme',theme)
            #cacheable.updateParam('tz',timezone)
            
        # set root xml:lang to preferences locale
        node.rootNode.childNodes[0].xml_set_attribute(
            (u'xml:lang',XML_NS),
            locale
        )
        
        #context.docIdParams.update(
        #    (
        #        theme,
        #        timezone,
        #        locale,
        #        account.agentId,
        #    ),
        #)
                
        return node